/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufc.quixada.adrs.comandos.visit;

import br.ufc.quixada.adrs.interfaces.Comando;
import br.ufc.quixada.adrs.model.Movimentacao;
import br.ufc.quixada.adrs.model.Produtor;
import br.ufc.quixada.adrs.model.RelatorioResult2;
import br.ufc.quixada.adrs.model.TipoAnimal;
import br.ufc.quixada.adrs.model.Visita;
import br.ufc.quixada.adrs.service.TipoAnimalService;
import br.ufc.quixada.adrs.util.UtilAdrs;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author ismaily
 */
public class CmdVisitMontarRelatorioQtMovimentacao implements Comando {

    public String executa(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession(true);


        //definição das mensagens de erro
        String[] mensagemErro = new String[7];
        mensagemErro[1] = "Por favor, selecione um ou todos os tipos de animais";
        mensagemErro[2] = "Por favor, especifique um período para o relatório";
        mensagemErro[3] = "Por favor, verifique o preenchemento da data que indica o início do período do relatório.";
        mensagemErro[4] = "Por favor, verifique o preenchemento da data que indica o fim do período do relatório.";
        mensagemErro[5] = "Por favor, selecione um ou alguns filtros para o relatório";
        mensagemErro[6] = "Período selecionado não contem visitas";


        boolean tdPeriodos = false;
        //saber se foi marcado todos os períodos
        String todosPeriodos = request.getParameter("todosPeriodos");
        if (todosPeriodos != null) {
            tdPeriodos = true;
        }

        //Datas de inicio e fim do relatório
        Date ini = null;
        Date fim = null;

        //setar o periodo marcado, caso não seja escolhido todos os períodos
        String dataIni = request.getParameter("dataInicio");
        if (dataIni != null) {
            ini = UtilAdrs.treatToDate(dataIni);
        }
        String dataFim = request.getParameter("dataFim");
        if (dataFim != null) {
            fim = UtilAdrs.treatToDate(dataFim);
        }

        //pega o tipo de animal
        String tipoAnimal = (String) request.getParameter("tipoAnimal");

        //pega os filtros marcados
        String nascidos = request.getParameter("nascidos");
        String roubados = request.getParameter("roubados");
        String mortos = request.getParameter("mortos");
        String comprados = request.getParameter("comprados");
        String vendidos = request.getParameter("vendidos");
        String exibirRelatorioDetalahdoReb = request.getParameter("detalharRelatorioMovimentacao");



        //todos os produtores selecionados
        ArrayList<Produtor> prods = (ArrayList<Produtor>) session.getAttribute("produtoresSelecionados");

        //estrutura onde será armazenado os dados dos relatórios
        ArrayList<RelatorioResult2> result = new ArrayList<RelatorioResult2>();

        //metodo que valida os campos(se foram todos preenchido) e retorna o codigo do erro a ser exibido na tela
        int codErro = validaCampos(tipoAnimal, todosPeriodos, dataIni, dataFim, nascidos, roubados, mortos, comprados, vendidos);
        if (codErro != 1) {
            session.setAttribute("erro", mensagemErro[codErro * (-1)]);
            return "/visit/visit_monta_relatorio_qt_passo_quatro.jsp";
        }

        //Se não foi marquado todos os periodos temos que verificar se tem alguma visita na data especificada
        if (todosPeriodos == null || todosPeriodos.trim().isEmpty()) {
            //se não houver visita retornamos com a mensagem 6(ver acima)
            if (!validaData(ini, fim, prods)) {
                session.setAttribute("erro", mensagemErro[6]);
                return "/visit/visit_monta_relatorio_qt_passo_quatro.jsp";
            }
        }

        //guarda o tipo de animal marcado na tela
        TipoAnimal tAnimal = null;

        //um booleano que indica se o todos os animais foi marcado ou não
        boolean todosOstiposAnimais = true;

        //se não foi marcado o booleano recebe falso e guardamos o tipo marcado no objeto tAnimal
        if (!tipoAnimal.equalsIgnoreCase("todos")) {
            todosOstiposAnimais = false;
            Long idTipo = Long.parseLong(tipoAnimal);
            tAnimal = new TipoAnimalService().getTipoAnimalById(idTipo);
            tipoAnimal = tAnimal.getTipo();
        }



        RelatorioResult2 r = null;

        for (Produtor p : prods) {
            //Para cada produtor temos uma estrutura RelatorioResult, onde armazena seus fitros e dadas
            r = new RelatorioResult2();
            r.setPrudutor(p);

            if (nascidos != null) {
                //método que retorna o número de nascidos(ver detalhes no método)
                totalNascidos(todosPeriodos, p, ini, fim, tAnimal, todosOstiposAnimais, r);

            }
            if (roubados != null) {
                //método que retorna o número de nascidos(ver detalhes no método)
                totalRoubados(todosPeriodos, p, ini, fim, tAnimal, todosOstiposAnimais, r);
            }
            if (comprados != null) {
                //método que retorna o número de nascidos(ver detalhes no método)
                totalComprados(todosPeriodos, p, ini, fim, tAnimal, todosOstiposAnimais, r);
            }
            if (vendidos != null) {
                //método que retorna o número de nascidos(ver detalhes no método)
                totalVendidos(todosPeriodos, p, ini, fim, tAnimal, todosOstiposAnimais, r);
            }
            if (mortos != null) {
                //método que retorna o número de nascidos(ver detalhes no método)
                totalMortos(todosPeriodos, p, ini, fim, tAnimal, todosOstiposAnimais, r);
            }

            //Ornade os valores do filtros por ordem alfabética
            r.ordenarValoresFiltros();
            //adiciona o relatorio do produtor p no ArrayList<RelatorioResult>, ou seja, os dados de todos os produtores para compor o relatório
            result.add(r);
        }


        //Exibir qual periodo foi marcado
        String periodo = "de " + getPrimeiraDataQuestionario(prods) + " a " + getUltimaDataQuestionario(prods);
        if (todosPeriodos == null) {
            periodo = "de " + dataIni + " a " + dataFim;
        }


        //arrays que seram utilizados para compor a parte geral do relatório
        List<String> filtros = result.get(0).getFiltrosMarcados();
        List<Integer> dados = this.getTotalDados(result);


        //setar valores na sessão
        session.setAttribute("periodo", periodo);
        session.setAttribute("relatorioResult", result);
        session.setAttribute("tipoAnimal", tipoAnimal);
        session.setAttribute("somaTotal", dados);
        session.setAttribute("filtros", filtros);
        session.setAttribute("datalharMovimentacao", exibirRelatorioDetalahdoReb);
        return "/visit/relatorio_qt_gerado.jsp";



    }


    /*Método que verfica se todos os campos foi devidademente preenchido*/
    private int validaCampos(String tipoAnimal, String tdPeriodos, String dataIni, String dataFim, String nascidos, String roubados, String mortos, String comprados, String vendidos) {
        if (tipoAnimal == null || tipoAnimal.trim().isEmpty()) {
            return -1;
        }
        if (tdPeriodos == null && ((dataFim == null || dataFim.trim().isEmpty()) || (dataIni == null || dataIni.trim().isEmpty()))) {
            return -2;
        }
        if (tdPeriodos == null && !UtilAdrs.validaData(dataIni)) {
            return -3;
        }
        if (tdPeriodos == null && !UtilAdrs.validaData(dataFim)) {
            return -4;
        }
        if (nascidos == null && roubados == null && mortos == null && comprados == null && vendidos == null) {
            return -5;
        }
        return 1;
    }

    /*Método que verifica se há visitas no período marcado*/
    private boolean validaData(Date ini, Date fim, ArrayList<Produtor> prods) {

        if (ini == null || fim == null) {
            return false;
        }
        if (ini.after(fim)) {
            return false;
        }
        for (Produtor p : prods) {
            List<Visita> visitas = p.getVisitas();
            for (Visita a : visitas) {
                if (a.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                Date visi = a.getData();
                if ((visi.before(fim) || visi.equals(fim)) && (visi.after(ini) || visi.equals(ini))) {
                    return true;
                }
            }
        }
        return false;
    }

    private void totalRoubados(String todosPeriodos, Produtor prods, Date ini, Date fim, TipoAnimal tipo, boolean todosOsTipos, RelatorioResult2 r) {

        List<Visita> visitas = prods.getVisitas();
        boolean tdPeriodo = false;
        if (todosPeriodos != null) {
            tdPeriodo = true;
        }
        int roubados = 0;
        int roubadosTemp = 0;
        for (Visita v : visitas) {
            roubadosTemp = 0;
            Date visi = v.getData();
            if (tdPeriodo || ((visi.before(fim) || visi.equals(fim)) && (visi.equals(ini) || visi.after(ini)))) {
                if (v.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                List<Movimentacao> m = v.getQuestionarioQuantitativo().getMovimentacoes();
                for (Movimentacao mov : m) {
                    if (todosOsTipos || mov.getTipoAnimal().getId().equals(tipo.getId())) {
                        roubados += mov.getRoubados();
                        roubadosTemp += mov.getRoubados();
                    }
                }
                r.setFiltroDado("Roubados", roubadosTemp, visi);
            }
        }
        r.setFiltroDadoSubTotal("Roubados", roubados);
    }

    private void totalComprados(String todosPeriodos, Produtor prods, Date ini, Date fim, TipoAnimal tipo, boolean todosOsTipos, RelatorioResult2 r) {

        List<Visita> visitas = prods.getVisitas();
        boolean tdPeriodo = false;
        if (todosPeriodos != null) {
            tdPeriodo = true;
        }
        int comprados = 0;
        int compradosTemp = 0;
        for (Visita v : visitas) {
            compradosTemp = 0;
            Date visi = v.getData();
            if (tdPeriodo || ((visi.before(fim) || visi.equals(fim)) && (visi.equals(ini) || visi.after(ini)))) {
                if (v.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                List<Movimentacao> m = v.getQuestionarioQuantitativo().getMovimentacoes();
                for (Movimentacao mov : m) {
                    if (todosOsTipos || mov.getTipoAnimal().getId().equals(tipo.getId())) {
                        comprados += mov.getComprados();
                        compradosTemp += mov.getComprados();
                    }
                }
                r.setFiltroDado("Comprados", compradosTemp, visi);
            }
        }
        r.setFiltroDadoSubTotal("Comprados", comprados);
    }

    private void totalVendidos(String todosPeriodos, Produtor prods, Date ini, Date fim, TipoAnimal tipo, boolean todosOsTipos, RelatorioResult2 r) {

        List<Visita> visitas = prods.getVisitas();
        boolean tdPeriodo = false;
        if (todosPeriodos != null) {
            tdPeriodo = true;
        }
        int vendidos = 0;
        int vendidosTemp = 0;
        for (Visita v : visitas) {
            vendidosTemp = 0;
            Date visi = v.getData();
            if (tdPeriodo || ((visi.before(fim) || visi.equals(fim)) && (visi.equals(ini) || visi.after(ini)))) {
                if (v.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                List<Movimentacao> m = v.getQuestionarioQuantitativo().getMovimentacoes();
                for (Movimentacao mov : m) {
                    if (todosOsTipos || mov.getTipoAnimal().getId().equals(tipo.getId())) {
                        vendidos += mov.getVendidos();
                        vendidosTemp += mov.getVendidos();
                    }
                }
                r.setFiltroDado("Vendidos", vendidosTemp, visi);
            }
        }
        r.setFiltroDadoSubTotal("Vendidos", vendidos);
    }

    private void totalMortos(String todosPeriodos, Produtor prods, Date ini, Date fim, TipoAnimal tipo, boolean todosOsTipos, RelatorioResult2 r) {

        List<Visita> visitas = prods.getVisitas();
        boolean tdPeriodo = false;
        if (todosPeriodos != null) {
            tdPeriodo = true;
        }
        int mortos = 0;
        int mortosTemp = 0;
        for (Visita v : visitas) {
            mortosTemp = 0;
            Date visi = v.getData();
            if (tdPeriodo || ((visi.before(fim) || visi.equals(fim)) && (visi.equals(ini) || visi.after(ini)))) {
                if (v.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                List<Movimentacao> m = v.getQuestionarioQuantitativo().getMovimentacoes();
                for (Movimentacao mov : m) {
                    if (todosOsTipos || mov.getTipoAnimal().getId().equals(tipo.getId())) {
                        mortos += mov.getMortos();
                        mortosTemp += mov.getMortos();
                    }
                }
                r.setFiltroDado("Mortos", mortosTemp, visi);
            }
        }
        r.setFiltroDadoSubTotal("Mortos", mortos);
    }

    private void totalNascidos(String todosPeriodos, Produtor prods, Date ini, Date fim, TipoAnimal tipo, boolean todosOsTipos, RelatorioResult2 r) {

        List<Visita> visitas = prods.getVisitas();
        boolean tdPeriodo = false;
        if (todosPeriodos != null) {
            tdPeriodo = true;
        }
        int nascidos = 0;
        int nascidosTemp = 0;
        for (Visita v : visitas) {
            nascidosTemp = 0;
            Date visi = v.getData();
            if (tdPeriodo || ((visi.before(fim) || visi.equals(fim)) && (visi.equals(ini) || visi.after(ini)))) {
                if (v.getQuestionarioQuantitativo() == null) {
                    continue;
                }
                List<Movimentacao> m = v.getQuestionarioQuantitativo().getMovimentacoes();
                for (Movimentacao mov : m) {
                    if (todosOsTipos || mov.getTipoAnimal().getId().equals(tipo.getId())) {
                        nascidos += mov.getNascidos();
                        nascidosTemp += mov.getNascidos();
                    }

                }
                r.setFiltroDado("Nascidos", nascidosTemp, visi);
            }
        }
        r.setFiltroDadoSubTotal("Nascidos", nascidos);
    }

    public String getPrimeiraDataQuestionario(ArrayList<Produtor> produtores) {

        Date primeira = new Date();
        List<Visita> visitas;
        for (Produtor p : produtores) {
            visitas = p.getVisitas();
            if (visitas == null) {
                continue;
            }
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQuantitativo()) {
                    continue;
                }
                Date dAux = v.getData();
                if (primeira.after(dAux)) {
                    primeira = dAux;
                }

            }
        }
        return UtilAdrs.treatToString(primeira);
    }

    public String getUltimaDataQuestionario(ArrayList<Produtor> produtores) {

        Date ultima = null;
        List<Visita> visitas;
        for (Produtor p : produtores) {
            visitas = p.getVisitas();
            if (visitas == null) {
                continue;
            }
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQuantitativo()) {
                    continue;
                }
                Date dAux = v.getData();
                if (ultima == null || ultima.before(dAux)) {
                    ultima = dAux;
                }
            }
        }
        return UtilAdrs.treatToString(ultima);
    }

    public List<Integer> getTotalDados(ArrayList<RelatorioResult2> result) {

        List<Integer> valores = new ArrayList<Integer>();
        for (int i = 0; i < getTamanhoRelatorioGeral(result); i++) {
            int cont = 0;
            for (RelatorioResult2 r : result) {
                cont += r.getSubtotal(i);
            }
            valores.add(i, cont);
        }
        for (RelatorioResult2 r : result) {
            List<Date> datas = r.getDatas();

            for (Date d : datas) {
                r.ordenaFiltroByData(d);
            }
        }
        return valores;
    }

    int getTamanhoRelatorioGeral(ArrayList<RelatorioResult2> result) {

        for (RelatorioResult2 r : result) {
            if (r.getFiltrosMarcados() != null && r.getSubTotal().size() > 0) {
                return r.getSubTotal().size();
            }
        }
        return 0;
    }
    
}
